package kayao.client.data;

import java.util.Vector;
import kayao.client.scene.objects.BuildingNode;
import kayao.client.scene.objects.CarCamera;
import kayao.client.scene.objects.CarNode;
import kayao.client.scene.objects.Entity;
import kayao.client.scene.objects.KayaoWorld;
import kayao.common.*;
import android.content.Context;
import com.chopsticks3d.scene.Light;
import com.chopsticks3d.scene.LightNode;
import com.chopsticks3d.scene.SceneNode;

public class SharedMemory {
	private static SharedMemory sSingleton = new SharedMemory();
	private Context mContext;
	private Vector<Subscriber> mSubscribers = new Vector<Subscriber>();
	private Client[] mClients = new Client[KayaoValues.MAX_NUMBER_OF_CLIENTS];
	private Client[] mTeamClients = new Client[KayaoValues.MAX_NUMBER_OF_CLIENTS / KayaoValues.NUMBER_OF_TEAMS];
	private Vector<Entity> mEntities = new Vector<Entity>();
	private MissionData mMissionData;
	private int mLocalId;
	private int mLocalTeamId;
	private String mName;
	private Client myself;

	private SceneNode mScene;
	private CarNode mAvatar;
	private CarCamera mCamera;
	private King mKing;
	private Slave mSlave;

	//Here the received and outgoing messages are saved
	private String mOutgoingMessage=null;
	private String mIncomingMessage=null;

	// Used for various operations, declared here to avoid memory allocations later on
	private int i;
	private Client client;

	private SharedMemory() {
		for (i = 0; i < mClients.length; i++) {
			mClients[i] = null;
		}
		for (i = 0; i < mTeamClients.length; i++) {
			mTeamClients[i] = null;
		}
	}

	public void reset() {
		sSingleton = new SharedMemory();
		mSubscribers = null;
		mClients = null;
		mTeamClients = null;
	}

	public Client getMyself(){
		return myself;
	}

	public void setKing(King king){
		this.mKing = king;
	}

	public King getKing(){
		return mKing;
	}

	public void deleteKing(){
		mKing = null;
	}

	public Slave getSlave(){
		return mSlave;
	}

	public void createWorld(Context context) {
		mContext = context;

		// Create the initial scene
		mScene = new KayaoWorld();

		mAvatar = new CarNode();
		mAvatar.setTranslationX(-0.7f);
		mAvatar.setTranslationZ(-2);

		mCamera = new CarCamera(mAvatar);

		mScene.addChild(mAvatar);
	}

	public static SharedMemory getInstance() {
		return sSingleton;
	}

	public Context getContext() {
		return mContext;
	}

	public SceneNode getScene() {
		return mScene;
	}

	public CarNode getAvatar() {
		return mAvatar;
	}

	public CarCamera getCamera() {
		return mCamera;
	}

	public int getLocalId() {
		return mLocalId;
	}

	public void setLocalId(int localId) {
		mLocalId = localId;
	}

	public int getLocalTeamId() {
		return mLocalTeamId;
	}

	public void setLocalTeamId(int localTeamId) {
		mLocalTeamId = localTeamId;
	}

	public String getName() {
		return mName;
	}

	public void setName(String name) {
		mName = name;
	}

	public void addClient(Client client) {
		mClients[client.getId()-1] = client;

		if (client.getTeam() == mLocalTeamId) {
			for (i = 0; i < mTeamClients.length; i++) {
				if (mTeamClients[i] == null) {
					mTeamClients[i] = client;
					break;
				}
			}
		}
	}

	public Client getClientById(int id){
		return mClients[id-1];
	}

	public Client getClientByIp(String ip){
		for (i = 0; i < mClients.length; i++) {
			if (mClients[i]!=null && mClients[i].getIP().equals(ip)) {
				return mClients[i];
			}
		}
		return null;
	}

	public void removeClient(int id) {
		client = mClients[id-1];
		removeSubscriber(id);

		if (client.getTeam() == mLocalTeamId) {
			for (i = 0; i < mTeamClients.length; i++) {
				if (mTeamClients[i] == client) {
					mTeamClients[i] = null;
					break;
				}
			}
		}

		mClients[id-1] = null;
	}

	public boolean hasClient(int id){
		if(mClients[id-1]==null)
			return false;
		return true;
	}

	public Client [] getTeamMates() {
		return mTeamClients;
	}
	
	public void printSubscribers(){
		System.out.println("!!SharedMemory.printSubscribers size: "+mSubscribers.size());
		for(int i=0; i<mSubscribers.size(); i++){
			System.out.println("!! "+mSubscribers.get(i).toString());
		}
		System.out.println("!!------------------------------");
	}

	public void updateSubscriberList(Vector<Integer> subscribers, int kingdom){
		System.out.println("(SharedMemory.updateSubscriberList) newlist: "+subscribers.size()+" oldlist: "+mSubscribers.size());
		
		//for each new suscriber,or we add the kingdom or we add the suscriber
		for(int i: subscribers){
			boolean newSubscriber = true;
			for(Subscriber s: mSubscribers){
				if(s.getId()==i)
				{
					s.addKingdom(kingdom);
					newSubscriber = false;
					break;
				}
			}
			if(newSubscriber)
				mSubscribers.add(new Subscriber(i, kingdom));
		}
		//for each old suscriber, we remove the kingdom if it's not anymore
		for(Subscriber s: mSubscribers){
			boolean referred = false;
			for(int i: subscribers){
				if(s.getId()==i)
				{
					referred = true;
					break;
				}
			}
			if(!referred)
			{
				s.removeKingdom(kingdom);
				if(s.isEmpty())
					System.out.println("(SharedMemory.updateSubscriberList) subscriber: "+s.getId()+" removed");
					mSubscribers.remove(s);
			}
		}
	}

	public Vector<Subscriber> getSubscribers(){
		return mSubscribers;
	}

	public void removeSubscriber(int id){
		for(Subscriber s: mSubscribers){
			if(s.getId()==id){
				mSubscribers.remove(s);
				return;
			}
		}
	}

	public CarNode getCarById(int id) {
		for(int i = 0; i < mEntities.size(); i++) {
			Entity entity = mEntities.get(i);
			if (entity.getOwner().getId() == id) {
				if (entity instanceof CarNode) {
					return (CarNode)entity;
				}
			}
		}
		return null;
	}

	public void addEntity(Entity entity) {
		mEntities.add(entity);
		mScene.addChild(entity);
	}
	
	public Vector<Entity> getEntitiesAsVector() {
		return mEntities;
	}

	public void setClient(Client client2) {
		myself=client2;
	}

	public String getOutgoingMessage() {
		return mOutgoingMessage;
	}

	public void setIncomingMessage(String message) {
		mIncomingMessage=message;
	}
	
	public void createMissionData(float x, float y, float z){
		mMissionData = new MissionData(x,y,z);
	}

}
